package org.particlethink.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.particlethink.auth.DefaultUser;
import org.particlethink.config.RequestConfig;
import org.particlethink.context.Context;
import org.particlethink.context.DefaultContext;
import org.particlethink.entry.PlanTyp;
import org.particlethink.mapper.CategoryMapper;
import org.particlethink.mapper.MaterialMapper;
import org.particlethink.mapper.PlanMaterialMapper;
import org.particlethink.mapper.impl.ProMaterialRequestHelper;
import org.particlethink.model.*;
import org.particlethink.request.BatchPlanRequest;
import org.particlethink.request.MaterialListRequest;
import org.particlethink.response.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.*;
import java.util.stream.Collectors;

@Tag(name = "物料信息")
@RestController
@RequestMapping("/material")
public class MaterialController {

    @Autowired
    private MaterialMapper materialMapper;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private PlanMaterialMapper planMaterialMapper;
    @Autowired
    ResourceLoader resourceLoader;

    @Autowired
    private RequestConfig requestConfig;

    @Operation(description = "物料列表，是一个树状的")
    @PostMapping("/list")
    public BaseResponse<List<MaterialListResponse>> queryMaterials(@RequestBody MaterialListRequest request) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();


        Context ctx = DefaultContext.Builder.background().withValue("token", ((DefaultUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUser().getToken());

        List<Integer> filterMaterialIdList = new ArrayList<>();

        if (request.getMasterPlanId() != null && request.getMasterPlanId() > 0) {
            List<PlanMaterial> planMaterials = planMaterialMapper.selectByPlanIDAndTyp(request.getMasterPlanId(), PlanTyp.Master);
            filterMaterialIdList = planMaterials.stream().map(PlanMaterial::getMaterialId).distinct().collect(Collectors.toList());
        }


        ProMaterialRequestHelper.MaterialResponse materialResponse = materialMapper.Find(user.getToken(), filterMaterialIdList, request.getMaterialKindIds(), new ArrayList<>(), request.getPageNum(), request.getPageSize());
        if (materialResponse.getRows() == null || materialResponse.getRows().isEmpty()) {
            return BaseResponse.success(new ArrayList<>());
        }

        ArrayList<MaterialInfo> materials = new ArrayList<>();

        materialResponse.getRows().forEach(t -> {

            String categoryName;
            String parentCategoryName;
            String[] cate = t.getType().split("-");
            if (cate.length == 2) {
                categoryName = cate[1];
                parentCategoryName = cate[0];
            } else {
                parentCategoryName = "";
                categoryName = "";
            }


            t.getMaterialDetails().forEach(requestMaterial -> {

                MaterialInfo materialInfo = new MaterialInfo();
                materialInfo.setId(requestMaterial.getId());
                materialInfo.setName(requestMaterial.getName());
                materialInfo.setQuality(requestMaterial.getQualityStandard());
                materialInfo.setSpecification(requestMaterial.getSpecification());
                materialInfo.setNo(requestMaterial.getCode());
                materialInfo.setUnit(requestMaterial.getUnit());
                materialInfo.setTyp(requestMaterial.getModel());
                materialInfo.setCategoryId(requestMaterial.getCategoryId());
                materialInfo.setParentCategoryId(requestMaterial.getParentCategoryId());


                materialInfo.setCategory(new MaterialKindResponse(requestMaterial.getCategoryId(), categoryName));
                materialInfo.setParentCategory(new MaterialKindResponse(requestMaterial.getParentCategoryId(), parentCategoryName));
                materials.add(materialInfo);
            });
        });


        Map<String, Map<String, List<MaterialInfo>>> groupedMaterials = materials.stream()
                .collect(Collectors.groupingBy(
                        MaterialInfo::getCategoryId,
                        Collectors.groupingBy(MaterialInfo::getParentCategoryId)
                ));


        ArrayList<MaterialListResponse> result = new ArrayList<>();

        groupedMaterials.forEach((category, subMap) -> {


            List<MaterialListResponse.MaterialInfos> materialInfos = new ArrayList<>();


            subMap.forEach((subCategory, list) -> {
                if (list == null || list.isEmpty()) {
                    return;
                }
                MaterialInfo materialInfo = list.get(0);

                if (materialInfo.getCategory() == null) {
                    return;
                }

                materialInfos.add(new MaterialListResponse.MaterialInfos(list, materialInfo.getCategory().getId(), materialInfo.getCategory().getName()));


            });
            if (materialInfos == null || materialInfos.isEmpty()) {
                return;
            }

            if (materialInfos.get(0).getMaterials() == null || materialInfos.get(0).getMaterials().isEmpty()) {
                return;
            }
            MaterialKindResponse parentCategory = materialInfos.get(0).getMaterials().get(0).getParentCategory();

            if (parentCategory == null) {
                return;
            }


            result.add(new MaterialListResponse(materialInfos, parentCategory.getId(), parentCategory.getName(), materialResponse.getTotal()));
        });



        return BaseResponse.success(result);
    }


    @Operation(description = "根据物料大类获取供应商")
    @GetMapping("/supplier")
    public BaseResponse<List<SupplierResponse>> queryMaterials(
            @RequestParam(required = false)
            @Parameter(description = "物料计划大类编号，不传则是返回整个树状列表")
            String materialKindId
    ) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        DefaultUser defaultUser = (DefaultUser) authentication.getPrincipal();
        User user = defaultUser.getUser();

        Context ctx = DefaultContext.Builder.background().withValue("token", ((DefaultUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUser().getToken());
        List<Supplier> suppliers = materialMapper.selectByParentCategoryId(user.getToken(), materialKindId);
        List<SupplierResponse> collect = suppliers.stream().map(t -> {
            return new SupplierResponse(t);
        }).collect(Collectors.toList());

        return BaseResponse.success(collect);
    }


    @Operation(description = "物料大类树")
    @GetMapping("/tree")
    public BaseResponse<List<ProMaterialRequestHelper.MajorType>> tree() {
        String token = ((DefaultUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUser().getToken();
        try {

            List<ProMaterialRequestHelper.MajorType> majorTypes = ProMaterialRequestHelper.listMajorTypes(requestConfig.getUrl(), token);
            return BaseResponse.success(majorTypes);

        } catch (URISyntaxException | IOException e) {
            throw new RuntimeException(e);
        }
    }


    @Operation(description = "总计划下载模板")
    @GetMapping("/master/template/download")
    public void masterTemplate(
            HttpServletResponse response
    ) throws IOException {
        Resource resource = resourceLoader.getResource("classpath:" + "material_master_template.xlsx");
        InputStream inputStream = resource.getInputStream();

//        response.reset();
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + "material_master_template.xlsx");

        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");


        ServletOutputStream outputStream = response.getOutputStream();
        byte[] b = new byte[1024];
        int len;
//从输入流中读取一定数量的字节，并将其存储在缓冲区字节数组中，读到末尾返回-1
        while ((len = inputStream.read(b)) > 0) {
            outputStream.write(b, 0, len);
        }
        inputStream.close();
    }


    @Operation(description = "批次计划下载模板")
    @GetMapping("/batch/template/download")
    public void batchTemplate(
            HttpServletResponse response
    ) throws IOException {
        Resource resource = resourceLoader.getResource("classpath:" + "material_batch_template.xlsx");
        InputStream inputStream = resource.getInputStream();

        response.reset();
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + "material_batch_template.xlsx");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");


        ServletOutputStream outputStream = response.getOutputStream();
        byte[] b = new byte[1024];
        int len;
//从输入流中读取一定数量的字节，并将其存储在缓冲区字节数组中，读到末尾返回-1
        while ((len = inputStream.read(b)) > 0) {
            outputStream.write(b, 0, len);
        }
        inputStream.close();
    }
}
